//线程池的头文件

#ifndef  __THREAD_POOL_H__
#define  __THREAD_POOL_H__

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <error.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/epoll.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/uio.h>
#include <sys/sendfile.h>

#define SIZE(a) (sizeof(a)/sizeof(a[0]))

typedef  void (*sighandler_t)(int);

//main 参数处理
#define ARGS_CHECK(argc,num) {\
    if(argc !=num){\
        fprintf(stderr,"ARGS ERROR!\n");\
        return -1;\
    }}
//报错
#define ERROR_CHECK(ret,num,msg){\
    if(ret==num){\
        perror(msg);\
        return -1;\
    }}

#define THREAD_ERROR_CHECK(ret,func){\
    if(ret!=0){\
        fprintf(stderr,"%s:%s\n",func,strerror(ret));\
    }}


//命令类型，登陆状态
typedef enum{
    CMD_TYPE_PWD=1, //当前目录
    CMD_TYPE_LS, //列出目录
    CMD_TYPE_CD,//切换目录
    CMD_TYPE_MKDIR, //创建目录
    CMD_TYPE_RMDIR,//删除
    CMD_TYPE_PUTS,//上传
    CMD_TYPE_GETS,//下载
    CMD_TYPE_NOTCMD, //错误命令


    TASK_LOGIN_SECTION1 = 100, //第一阶段
    TASK_LOGIN_SECTION1_RESP_OK, //成功
    TASK_LOGIN_SECTION1_RESP_ERROR,//失败
    TASK_LOGIN_SECTION2,//第二阶段
    TASK_LOGIN_SECTION2_RESP_OK,//成功
    TASK_LOGIN_SECTION2_RESP_ERROR,//失败

}CmdType;

typedef struct {
    int len; //内容长度
    CmdType type;
    char buff[1000]; //内容本身
}train_t;

typedef struct task_s{
    int peerfd; //与client进行通信的套接字
    int epfd; //epoll的实例
    CmdType type;//  任务类型
    char data[1000];//  任务携带的数据
    struct task_s* pNext;//指向链表中下一个任务的指针
}task_t;

// 实现线程安全的任务队列
typedef struct task_queue_s{
    task_t* pFront; //第一个任务指针，队头
    task_t* pRear;//最后一个任务指针，队尾
    int queSize; //队列任务数量
    pthread_mutex_t mutex;//互斥锁
    pthread_cond_t cond;//线程同步
    int flag;//状态
}task_queue_t;

typedef  struct threadpool_s{
    pthread_t* pthreads; //存储线程id
    int pthreadNum;//线程池线程数量
    task_queue_t que; //关联的任务队列
}threadpool_t;

//函数实现
//任务队列相关函数
int queueInit(task_queue_t* que); //初始化
int queueDestroy(task_queue_t* que);//销毁任务队列
int queueIsEmpty(task_queue_t* que); //判断是否为空
int taskSize(task_queue_t* que); //获取队列中的任务数量
int taskEnque(task_queue_t* que);// 将任务加入队列
task_t* taskDeque(task_queue_t* que); //从队列中取出任务
int broadcastAll(task_queue_s* que); //唤醒所有等待在队列条件变量上的线程

//线程池相关函数
int threadpoolInit(threadpool_t*,int num); //初始化线程池
int threadpoolDestroy(threadpool_t*); //销毁线程池
int threadpoolStart(threadpool_t*);  //启动线程池
int threadpoolStop(threadpool_t*);//停止线程池

//网络通信相关函数

int tcpInint(const char* ip,const char* port); //初始化TCP服务器，创建，绑定，监听 
int addEpollReadfd(int epfd,int fd);//添加监听读事件文件描述符
int delEpollReadfd(int epfd,int fd);//移除读事件文件描述符
int treansferFile(int sockfd);//传输文件
int sendn(int sockfd,const void* buff,int len);//保证发送制定长度数据
int recvn(int sockfd,void* buff,int len);//保证接受制定长度的数据

//处理客户端发过来的消息
void handleMessage(int sockfd, int epfd, task_queue_t * que);
//执行任务的总的函数
void doTask(task_t* task);
//具体命令执行
void cdCommand(task_t * task);
void lsCommand(task_t * task);
void pwdCommand(task_t * task);
void mkdirCommand(task_t * task);
void rmdirCommand(task_t * task);
void notCommand(task_t * task);
void putsCommand(task_t * task);
void getsCommand(task_t * task);

//用户登录的操作
void userLoginCheck1(task_t * task);
void userLoginCheck2(task_t * task);


#endif
